<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Smoothing Images</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d5/d10/tutorial_js_root.html">OpenCV.js Tutorials</a></li><li class="navelem"><a class="el" href="../../d2/df0/tutorial_js_table_of_contents_imgproc.html">Image Processing</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Smoothing Images </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goals </h2>
<ul>
<li>Blur the images with various low pass filters</li>
<li>Apply custom-made filters to images (2D convolution)</li>
</ul>
<h2>2D Convolution ( Image Filtering ) </h2>
<p>As in one-dimensional signals, images also can be filtered with various low-pass filters(LPF), high-pass filters(HPF) etc. LPF helps in removing noises, blurring the images etc. HPF filters helps in finding edges in the images.</p>
<p>OpenCV provides a function <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga27c049795ce870216ddfb366086b5a04" title="Convolves an image with the kernel. ">cv.filter2D()</a></b> to convolve a kernel with an image. As an example, we will try an averaging filter on an image. A 5x5 averaging filter kernel will look like below:</p>
<p class="formulaDsp">
\[K = \frac{1}{25} \begin{bmatrix} 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 \\ 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 \\ 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 \\ 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 \\ 1 &amp; 1 &amp; 1 &amp; 1 &amp; 1 \end{bmatrix}\]
</p>
<p>We use the functions: <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga27c049795ce870216ddfb366086b5a04" title="Convolves an image with the kernel. ">cv.filter2D</a> (src, dst, ddepth, kernel, anchor = new <a class="el" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">cv.Point</a>(-1, -1), delta = 0, borderType = <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5afe14c13a4ea8b8e3b3ef399013dbae01" title="same as BORDER_REFLECT_101 ">cv.BORDER_DEFAULT</a>)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>input image. </td></tr>
    <tr><td class="paramname">dst</td><td>output image of the same size and the same number of channels as src. </td></tr>
    <tr><td class="paramname">ddepth</td><td>desired depth of the destination image. </td></tr>
    <tr><td class="paramname">kernel</td><td>convolution kernel (or rather a correlation kernel), a single-channel floating point matrix; if you want to apply different kernels to different channels, split the image into separate color planes using split and process them individually. </td></tr>
    <tr><td class="paramname">anchor</td><td>anchor of the kernel that indicates the relative position of a filtered point within the kernel; the anchor should lie within the kernel; default value new <a class="el" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">cv.Point</a>(-1, -1) means that the anchor is at the kernel center. </td></tr>
    <tr><td class="paramname">delta</td><td>optional value added to the filtered pixels before storing them in dst. </td></tr>
    <tr><td class="paramname">borderType</td><td>pixel extrapolation method(see <a class="el" href="../../d2/de8/group__core__array.html#ga209f2f4869e304c82d07739337eae7c5">cv.BorderTypes</a>).</td></tr>
  </table>
  </dd>
</dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_filtering_filter.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h2>Image Blurring (Image Smoothing) </h2>
<p>Image blurring is achieved by convolving the image with a low-pass filter kernel. It is useful for removing noises. It actually removes high frequency content (eg: noise, edges) from the image. So edges are blurred a little bit in this operation. (Well, there are blurring techniques which doesn't blur the edges too). OpenCV provides mainly four types of blurring techniques.</p>
<h3>1. Averaging</h3>
<p>This is done by convolving image with a normalized box filter. It simply takes the average of all the pixels under kernel area and replace the central element. This is done by the function <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga8c45db9afe636703801b0b2e440fce37" title="Blurs an image using the normalized box filter. ">cv.blur()</a></b> or <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#gad533230ebf2d42509547d514f7d3fbc3" title="Blurs an image using the box filter. ">cv.boxFilter()</a></b>. Check the docs for more details about the kernel. We should specify the width and height of kernel. A 3x3 normalized box filter would look like below:</p>
<p class="formulaDsp">
\[K = \frac{1}{9} \begin{bmatrix} 1 &amp; 1 &amp; 1 \\ 1 &amp; 1 &amp; 1 \\ 1 &amp; 1 &amp; 1 \end{bmatrix}\]
</p>
<p>We use the functions: <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga8c45db9afe636703801b0b2e440fce37" title="Blurs an image using the normalized box filter. ">cv.blur</a> (src, dst, ksize, anchor = new <a class="el" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">cv.Point</a>(-1, -1), borderType = <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5afe14c13a4ea8b8e3b3ef399013dbae01" title="same as BORDER_REFLECT_101 ">cv.BORDER_DEFAULT</a>)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>input image; it can have any number of channels, which are processed independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. </td></tr>
    <tr><td class="paramname">dst</td><td>output image of the same size and type as src. </td></tr>
    <tr><td class="paramname">ksize</td><td>blurring kernel size. </td></tr>
    <tr><td class="paramname">anchor</td><td>anchor point; anchor = new <a class="el" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">cv.Point</a>(-1, -1) means that the anchor is at the kernel center. </td></tr>
    <tr><td class="paramname">borderType</td><td>border mode used to extrapolate pixels outside of the image(see <a class="el" href="../../d2/de8/group__core__array.html#ga209f2f4869e304c82d07739337eae7c5">cv.BorderTypes</a>).</td></tr>
  </table>
  </dd>
</dl>
<p><b><a class="el" href="../../d4/d86/group__imgproc__filter.html#gad533230ebf2d42509547d514f7d3fbc3" title="Blurs an image using the box filter. ">cv.boxFilter</a> (src, dst, ddepth, ksize, anchor = new <a class="el" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">cv.Point</a>(-1, -1), normalize = true, borderType = <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5afe14c13a4ea8b8e3b3ef399013dbae01" title="same as BORDER_REFLECT_101 ">cv.BORDER_DEFAULT</a>)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>input image. </td></tr>
    <tr><td class="paramname">dst</td><td>output image of the same size and type as src. </td></tr>
    <tr><td class="paramname">ddepth</td><td>the output image depth (-1 to use <a class="el" href="../../d0/daf/group__projection.html#ga8b5e5413af41caf3f2a0bbf4cdf517a8" title="Returns the depth of a point transformed by a rigid transform. ">src.depth()</a>). </td></tr>
    <tr><td class="paramname">ksize</td><td>blurring kernel size. </td></tr>
    <tr><td class="paramname">anchor</td><td>anchor point; anchor = new <a class="el" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">cv.Point</a>(-1, -1) means that the anchor is at the kernel center. </td></tr>
    <tr><td class="paramname">normalize</td><td>flag, specifying whether the kernel is normalized by its area or not. </td></tr>
    <tr><td class="paramname">borderType</td><td>border mode used to extrapolate pixels outside of the image(see <a class="el" href="../../d2/de8/group__core__array.html#ga209f2f4869e304c82d07739337eae7c5">cv.BorderTypes</a>).</td></tr>
  </table>
  </dd>
</dl>
<dl class="section note"><dt>Note</dt><dd>If you don't want to use normalized box filter, use <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#gad533230ebf2d42509547d514f7d3fbc3" title="Blurs an image using the box filter. ">cv.boxFilter()</a></b>. Pass an argument normalize = false to the function.</dd></dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_filtering_blur.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>2. Gaussian Blurring</h3>
<p>In this, instead of box filter, gaussian kernel is used.</p>
<p>We use the function: <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1" title="Blurs an image using a Gaussian filter. ">cv.GaussianBlur</a> (src, dst, ksize, sigmaX, sigmaY = 0, borderType = <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5afe14c13a4ea8b8e3b3ef399013dbae01" title="same as BORDER_REFLECT_101 ">cv.BORDER_DEFAULT</a>)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>input image; the image can have any number of channels, which are processed independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. </td></tr>
    <tr><td class="paramname">dst</td><td>output image of the same size and type as src. </td></tr>
    <tr><td class="paramname">ksize</td><td>blurring kernel size. </td></tr>
    <tr><td class="paramname">sigmaX</td><td>Gaussian kernel standard deviation in X direction. </td></tr>
    <tr><td class="paramname">sigmaY</td><td>Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height, to fully control the result regardless of possible future modifications of all this semantics, it is recommended to specify all of ksize, sigmaX, and sigmaY. </td></tr>
    <tr><td class="paramname">borderType</td><td>pixel extrapolation method(see <a class="el" href="../../d2/de8/group__core__array.html#ga209f2f4869e304c82d07739337eae7c5">cv.BorderTypes</a>).</td></tr>
  </table>
  </dd>
</dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_filtering_GaussianBlur.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>3. Median Blurring</h3>
<p>Here, the function <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga564869aa33e58769b4469101aac458f9" title="Blurs an image using the median filter. ">cv.medianBlur()</a></b> takes median of all the pixels under kernel area and central element is replaced with this median value. This is highly effective against salt-and-pepper noise in the images. Interesting thing is that, in the above filters, central element is a newly calculated value which may be a pixel value in the image or a new value. But in median blurring, central element is always replaced by some pixel value in the image. It reduces the noise effectively. Its kernel size should be a positive odd integer.</p>
<p>We use the function: <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga564869aa33e58769b4469101aac458f9" title="Blurs an image using the median filter. ">cv.medianBlur</a> (src, dst, ksize)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>input 1, 3, or 4 channel image; when ksize is 3 or 5, the image depth should be cv.CV_8U, cv.CV_16U, or cv.CV_32F, for larger aperture sizes, it can only be cv.CV_8U. </td></tr>
    <tr><td class="paramname">dst</td><td>destination array of the same size and type as src. </td></tr>
    <tr><td class="paramname">ksize</td><td>aperture linear size; it must be odd and greater than 1, for example: 3, 5, 7 ...</td></tr>
  </table>
  </dd>
</dl>
<dl class="section note"><dt>Note</dt><dd>The median filter uses <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aa1de4cff95e3377d6d0cbe7569bd4e9f" title="aaaaaa|abcdefgh|hhhhhhh ">cv.BORDER_REPLICATE</a> internally to cope with border pixels.</dd></dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_filtering_medianBlur.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>4. Bilateral Filtering</h3>
<p><b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga9d7064d478c95d60003cf839430737ed" title="Applies the bilateral filter to an image. ">cv.bilateralFilter()</a></b> is highly effective in noise removal while keeping edges sharp. But the operation is slower compared to other filters. We already saw that gaussian filter takes the a neighbourhood around the pixel and find its gaussian weighted average. This gaussian filter is a function of space alone, that is, nearby pixels are considered while filtering. It doesn't consider whether pixels have almost same intensity. It doesn't consider whether pixel is an edge pixel or not. So it blurs the edges also, which we don't want to do.</p>
<p>Bilateral filter also takes a gaussian filter in space, but one more gaussian filter which is a function of pixel difference. Gaussian function of space make sure only nearby pixels are considered for blurring while gaussian function of intensity difference make sure only those pixels with similar intensity to central pixel is considered for blurring. So it preserves the edges since pixels at edges will have large intensity variation.</p>
<p>We use the function: <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga9d7064d478c95d60003cf839430737ed" title="Applies the bilateral filter to an image. ">cv.bilateralFilter</a> (src, dst, d, sigmaColor, sigmaSpace, borderType = <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5afe14c13a4ea8b8e3b3ef399013dbae01" title="same as BORDER_REFLECT_101 ">cv.BORDER_DEFAULT</a>)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>source 8-bit or floating-point, 1-channel or 3-channel image. </td></tr>
    <tr><td class="paramname">dst</td><td>output image of the same size and type as src. </td></tr>
    <tr><td class="paramname">d</td><td>diameter of each pixel neighborhood that is used during filtering. If it is non-positive, it is computed from sigmaSpace. </td></tr>
    <tr><td class="paramname">sigmaColor</td><td>filter sigma in the color space. A larger value of the parameter means that farther colors within the pixel neighborhood will be mixed together, resulting in larger areas of semi-equal color. </td></tr>
    <tr><td class="paramname">sigmaSpace</td><td>filter sigma in the coordinate space. A larger value of the parameter means that farther pixels will influence each other as long as their colors are close enough. When d&gt;0, it specifies the neighborhood size regardless of sigmaSpace. Otherwise, d is proportional to sigmaSpace. </td></tr>
    <tr><td class="paramname">borderType</td><td>border mode used to extrapolate pixels outside of the image(see <a class="el" href="../../d2/de8/group__core__array.html#ga209f2f4869e304c82d07739337eae7c5">cv.BorderTypes</a>).</td></tr>
  </table>
  </dd>
</dl>
<dl class="section note"><dt>Note</dt><dd>For simplicity, you can set the 2 sigma values to be the same. If they are small (&lt; 10), the filter will not have much effect, whereas if they are large (&gt; 150), they will have a very strong effect, making the image look "cartoonish". Large filters (d &gt; 5) are very slow, so it is recommended to use d=5 for real-time applications, and perhaps d=9 for offline applications that need heavy noise filtering.</dd></dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_filtering_bilateralFilter.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
 </p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:37 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
